package com.ljm.oss;

import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.*;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.List;

/**
 * 阿里巴巴oss对象存储工具类
 */
@Component
public class AliOssUtil {
    // Endpoint以杭州为例，其它Region请按实际情况填写。
    String endpoint = "oss-cn-beijing.aliyuncs.com";
    // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
    String accessKeyId = "LTAIW3UIYhYIq4LH";
    String accessKeySecret = "dmHF86MPuQsizXfJCUHADz0K0pdHF4";
    String securityToken=null;

    /**
     * 初始化客户端
     * @return 客户端
     */
    private OSSClient initOSSClient(){
        // 创建OSSClient实例。
        ClientConfiguration config=new ClientConfiguration();
        CredentialsProvider credsProvider=new DefaultCredentialProvider(accessKeyId,accessKeySecret,securityToken);
        return new OSSClient(endpoint,credsProvider,config);
    }

    private void closeOSSClient(OSSClient ossClient){
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    /**
     * 创建存储空间
     * @param bucketName 空间名称
     */
    public void createBucket(String bucketName){
        OSSClient ossClient=this.initOSSClient();
        //判断是否存在
        if(!ossClient.doesBucketExist(bucketName)){
            // 新建存储空间默认为标准存储类型，私有权限。
            ossClient.createBucket(bucketName);
        }
        this.closeOSSClient(ossClient);
    }

    /**
     * 列举存储空间
     * @return
     */
    public List<Bucket> getBuckets(){
        OSSClient ossClient=this.initOSSClient();
        List<Bucket> buckets = ossClient.listBuckets();
        this.closeOSSClient(ossClient);
        return buckets;
    }

    /**
     * 判断空间是否存在
     * @param bucketName 空间名称
     * @return 是否存在
     */
    public boolean doesBucketExist(String bucketName){
        OSSClient ossClient=this.initOSSClient();
        boolean exists = ossClient.doesBucketExist(bucketName);
        this.closeOSSClient(ossClient);
        return exists;
    }

    /**
     * 设置空间权限
     * @param cannedAccessControlList 权限枚举
     */
    public void setBucketAcl(String bucketName,CannedAccessControlList cannedAccessControlList){
        OSSClient ossClient=this.initOSSClient();
        // 设置存储空间的访问权限为私有。
        ossClient.setBucketAcl(bucketName,cannedAccessControlList);
        this.closeOSSClient(ossClient);
    }

    /**
     * 获取空间权限
     * @param bucketName 空间名称
     * @return 空间权限
     */
    public AccessControlList getBucketAcl(String bucketName){
        OSSClient ossClient=this.initOSSClient();
        // 获取存储空间的访问权限。
        AccessControlList acl = ossClient.getBucketAcl(bucketName);
        this.closeOSSClient(ossClient);
        return acl;
    }

    /**
     * 删除空间
     * @param bucketName 空间名称
     */
    public void deleteBucket(String bucketName){
        OSSClient ossClient=this.initOSSClient();
        // 删除存储空间。
        ossClient.deleteBucket(bucketName);
        this.closeOSSClient(ossClient);
    }

    /**
     * 上传对象
     * @param bucketName 空间名称
     * @param objName 对象名称
     * @param inputStream 流
     */
    public void putObject(String bucketName,String objName,InputStream inputStream){
        OSSClient ossClient=this.initOSSClient();
        // 上传文件流。
        ossClient.putObject(bucketName, objName, inputStream);
        this.closeOSSClient(ossClient);
    }

    /**
     * 上传对象
     * @param bucketName 空间名称
     * @param objName 对象名称
     * @param file 文件
     */
    public void putObject(String bucketName, String objName, File file){
        OSSClient ossClient=this.initOSSClient();
        // 上传文件流。
        ossClient.putObject(bucketName, objName, file);
        this.closeOSSClient(ossClient);
    }

    /**
     * 获取文件下载链接
     * @param bucketName 空间名称
     * @param objectName 对象名称
     * @return
     */
    public String getUrl(String bucketName,String objectName){
        OSSClient ossClient=this.initOSSClient();
        // 指定过期时间为10分钟。
        Date expiration = new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 365 * 100 );
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);
        req.setExpiration(expiration);
        URL signedUrl = ossClient.generatePresignedUrl(req);
        this.closeOSSClient(ossClient);
        return signedUrl.toExternalForm();
    }

    /**
     * 下载文件
     * @param bucketName 空间名称
     * @param objectName 对象名称
     * @return 对象信息
     */
    public OSSObject getObject(String bucketName,String objectName){
        OSSClient ossClient=this.initOSSClient();
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
        this.closeOSSClient(ossClient);
        return ossObject;
    }

    /**
     * 下载文件
     * @param bucketName 空间名称
     * @param objectName 对象名称
     * @return 对象内容流
     */
    public InputStream getObjectToInputStream(String bucketName,String objectName){
        OSSClient ossClient=this.initOSSClient();
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
        this.closeOSSClient(ossClient);
        return ossObject.getObjectContent();
    }

    /**
     * 下载文件到本地
     * @param bucketName 空间名称
     * @param objectName 对象名称
     * @param filePath 文件名称（全路径）
     */
    public void getObjectToLocal(String bucketName,String objectName,String filePath){
        OSSClient ossClient=this.initOSSClient();
        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖，不存在则新建。
        ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(filePath));
        this.closeOSSClient(ossClient);
    }
}
